# -*- coding: utf-8 -*-
#
# GmAnt
# http://www.royalar.cn/2009/11/gmant
#

import urllib
from lxml.html import fromstring
from string import Template
import StringIO
import os
import sys

from util import ReadConf

conf = ReadConf()

class GmAnt:
    def __init__(self):
        self.baseURL = 'http://www.google.cn/music/'
        self.lastURL = ''
        self.cacheDoc = ''

    def artistlibrary(self,params = {},keys = ''):
        ret = self._filter_al_params(params,keys)
        fname = 'cache_al_'+ret[0]['type']+'_'+ret[0]['region']
        if os.path.exists(fname):
            doc = self._get_document(fname,local=True)
        else:
            doc = self._get_document(self.baseURL+'artistlibrary?region='+ret[0]['region']+'&type='+ret[0]['type'],cache=fname)
        xpath = "//td[@class='artist_name']/a"
        if len(keys) == 1:
            xpath = "//div[@id='artist-section-%s']" % keys + xpath
        return self._get_link_by_xpath(doc,xpath)

    def search(self,keywords,pagestart=0):
        #执行搜索---仅根据关键词搜索专辑
        doc = self._get_document(self.baseURL+'search?start='+str(pagestart)+'&cat=album&q='+urllib.quote(keywords.decode('gbk').encode('utf-8')))
        #获取搜索结果数
        spanstr = (doc.xpath("//div[@id='main_content']/table[1]//span[@class='headline-item-selected']"))[0].text
        total = int(spanstr[3:-1])
        #结果列表
        if total>0:
            xpath = "//div[@id='album_list']//td[@class='Title']/a[1]"
            links = self._get_link_by_xpath(doc,xpath)
            for link in links:
                link['name'] = link['name'][1:-1]
            return (links,total)
        else:
            print 'no albums find'
            return ([],0)

    def artist(self,artistVo):
        #解析歌手页面，返回歌手的专辑列表
        doc = self._get_document(artistVo['href'])
        xpath = "//table[@class='AlbumInfo']/tr/td[1]/a[@name='LandingPageLink']"
        albums = self._get_link_by_xpath(doc,xpath)
        for album in albums:
            album['name'] = album['name'][1:-1]
        return albums

    def artistVo_by_albumVo(self,albumVo):
        #根据专辑信息解析出歌手信息
        doc = self._get_document(albumVo['href'])
        a = (doc.xpath("//table[@id='album_item']//table//td[@class='Description']/a"))[0]
        return {"name":a.text,"href":self._filter_url(a.attrib['href'])}

    def album(self,albumVo):
        #解析专辑页面，获取歌曲列表
        doc = self._get_document(albumVo['href'])
        xpath_song = "//td[@class='Title BottomBorder']/a"      #歌曲信息
        xpath_dl = "//td[@class='Icon BottomBorder'][3]/a"      #歌曲下载页面链接
        songs = self._get_link_by_xpath(doc,xpath_song)
        dls = self._get_link_by_xpath(doc,xpath_dl,'onclick')
        i=0
        for song in songs:
            #此处要对链接进行转化
            href = dls[i]['href']
            song['href'] = self.baseURL+'top100/musicdownload'+href[href.find('?'):]
            i += 1
        return songs

    def dl_album(self,albumVo,artistVo={},songs=[]):
        # songs 要下载的歌曲列表，亦即专辑内包含的歌曲
        if len(songs) == 0:
            songs = self.album(albumVo)
        if len(artistVo) == 0:
             artistVo = self.artistVo_by_albumVo(albumVo)
        infos={}
        infos['album'] = albumVo['name']
        infos['artist'] = artistVo['name']
        #路径
        savedir = Template(conf['save_dir']).substitute( infos )
        self._check_dir(savedir)  #检查路径
        number = 1
        for song in songs:
            infos.update(self.song_dlpage_by_url( song['href'] ))
            infos['tracknumber'] = str(number).zfill(2)
            number += 1
            filename = Template(conf['file_name']).substitute( infos )+'.'+infos['ext']
            self._dl_(infos['dllink'],savedir+filename,filename)


    def song_dlpage_by_url(self,url):
        #分析歌曲下载页面，获取歌曲的相关信息：歌曲名称、演唱者、后缀
        infos = {}
        doc = self._get_document(url)
        tds = doc.xpath("//tr[@class='meta-data-tr']/td")
        infos['title'],infos['singer'],infos['ext'] = tds[0].text,tds[1].text,tds[3].text.lower()
        a = doc.xpath("//div[2]/a")
        infos['dllink'] = 'http://www.google.cn'+a[0].attrib['href']
        return infos


    #private methods
    def _filter_al_params(self,params,keys=''):
        if not params['type'] in ('male','female','bandgroup'):
            params['type'] = 'female'
        if not params['region'] in ('cn','eu_us','jp_kr','other'):
            params['region'] = 'cn'
        keys = keys.upper()
        if keys!='' and  keys != 'OTHERS' and not (key>='A' and key<='Z'):
            keys =' '
        return (params,keys)



    def _dl_(self,source,target,tip=''):
        try:
            print 'downloading ',tip,'   ',
            urllib.urlretrieve(source, target ,self._dl_callback)
            print '    ok'
        except Exception,e:
            print '    error'

    def _check_dir(self,dir):
        if not os.path.exists(dir):
            os.makedirs(dir)

    def _get_document(self,url,local=False,cache=False):
        if url != self.lastURL:
            if local == True:
                file = open(url)
            else:
                try:
                    file = urllib.urlopen(url)
                except Exception,e:
                    print 'error:',e
            html = file.read()
            if cache:
                try:
                    f = open(cache,'w')
                    f.write(html)
                    f.close()
                except IOError,message:
                    print 'write cache file'
            #self.cacheDoc = etree.parse(StringIO.StringIO(html),parser = etree.HTMLParser())
            self.cacheDoc = fromstring(html)
            self.lastURL = url
        return self.cacheDoc

    def _get_link_by_xpath(self,doc,xpath,linkAttr = 'href'):
        links = []
        for a in doc.xpath(xpath):
            o = {}
            o['name'],attr = a.text_content(),a.attrib
            if attr.has_key(linkAttr):
                o['href'] = self._filter_url(attr[linkAttr])
            links.append(o)
        return links

    def _filter_url(self,url):
        url = urllib.unquote(url.replace('\\x','%'))
        if url[:10] == '/music/url':
            url = url[20:]
        elif url[:11] == 'window.open':
            url = url[26:]
        url = url[:(url.find('&'))]
        return 'http://www.google.cn/music/'+url

    def _dl_callback(self, blocks, block_size, total_size):
        if total_size > 0 and blocks >= 0:
            percentage = float(blocks) / (total_size/block_size+1) * 100
            sys.stdout.write('%3d%s\b\b\b\b' % (percentage,'%'))


